package com.ruoyi.project.system.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.druid.wall.violation.ErrorCode;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.HttpUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.Md5Util;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.SysCompany;
import com.ruoyi.project.system.domain.SysGood;
import com.ruoyi.project.system.service.ISysCompanyService;
import com.ruoyi.project.system.service.ISysGoodService;
import com.ruoyi.project.tool.swagger.UserController.SignUtil;
import okhttp3.HttpUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.project.system.mapper.SysLuckMapper;
import com.ruoyi.project.system.domain.SysLuck;
import com.ruoyi.project.system.service.ISysLuckService;
import org.springframework.transaction.annotation.Transactional;
import test.util.SequenceUtils;

/**
 * 中奖订单Service业务层处理
 *
 * @author theme
 * @date 2021-01-17
 */
@Service
public class SysLuckServiceImpl implements ISysLuckService {
    private Lock lock = new ReentrantLock(true);
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysLuckMapper sysLuckMapper;

    @Autowired
    private ISysGoodService sysGoodService;

    @Autowired
    private ISysCompanyService sysCompanyService;


    @Autowired
    private WxMaService wxMaService;

    /**
     * 查询中奖订单
     *
     * @param luckId 中奖订单ID
     * @return 中奖订单
     */
    @Override
    public SysLuck selectSysLuckById(Long luckId) {
        return sysLuckMapper.selectSysLuckById(luckId);
    }

    /**
     * 查询中奖订单列表
     *
     * @param sysLuck 中奖订单
     * @return 中奖订单
     */
    @Override
    public List<SysLuck> selectSysLuckList(SysLuck sysLuck) {
        return sysLuckMapper.selectSysLuckList(sysLuck);
    }

    @Override
    public List<SysLuck> selectSysResult(SysLuck sysLuck) {
        return sysLuckMapper.selectSysResult(sysLuck);
    }

    /**
     * 抽奖
     *
     * @param map
     * @return
     */

    @Override
    @Transactional
    public AjaxResult luck(Map map) {
        try {
            Long chance = 0l;
            SysCompany sysCompany = sysCompanyService.selectSysCompanyById(1l);
            chance = Long.valueOf(sysCompany.getChance());
            String bankUserSign = map.get("bankUserSign") + "";
            String keys = "LD166T";
            long time = System.currentTimeMillis() / 1000;
            //测试环境为0,正式环境为9
            String proof = "0";
            JSONArray prize = new JSONArray();
            JSONObject obj = new JSONObject();
            obj.put("id", "0");
            obj.put("name", sysCompany.getScore());
            prize.add(obj);
            String value = bankUserSign + proof + time + keys;
            String token = new String(Md5Util.md5(value));
            JSONObject data = new JSONObject();
            data.put("bank_user_sign", bankUserSign);
            data.put("proof", proof);
            data.put("time", time);
            data.put("token", token);
            data.put("prize", prize.toJSONString());
            System.out.println(data.toJSONString());
//            JSONObject jsonObject=new JSONObject();
            JSONObject jsonObject = HttpUtil.doPost("https://csp-brdc.dccnet.com.cn/weChatActivity/activity/qualificationQuery", data,null);
            if (!jsonObject.getString("code").equals("200")) {
                System.out.println(jsonObject.toJSONString());
                return  AjaxResult.error(201,jsonObject.getString("msg"));
            }
            String date = SequenceUtils.getCurentDate();
            String key = "serial.gooods:" + date;
            //** 自增 *//*
            long sequence = redisTemplate.opsForValue().increment(key);
            String orderNo = date + SequenceUtils.getSequence(sequence);
            List<SysGood> list = sysGoodService.selectSysGoodLists();
            if (list.isEmpty()) {
                //没中奖
                detail(null, map, orderNo,jsonObject);
                return AjaxResult.success();
            }
            SysGood good = new SysGood();
            good.setGoodId(0l);
            good.setChance(chance);
            if (chance != 0) {
                list.add(good);
            }
            int prizeIndex = getBulletPrizeIndex(list);
            SysGood sysGood1 = list.get(prizeIndex);
            if (sysGood1.getGoodId() == 0 || sysGood1.getStock() <= 0) {
                detail(null, map, orderNo,jsonObject);
                return AjaxResult.success();
            } else {
                detail(sysGood1, map, orderNo,jsonObject);
                return AjaxResult.success(sysGood1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("系统错误！");
        }
    }

    public void detail(SysGood sysGood, Map map, String orderNo,JSONObject jsonObject) throws Exception {
        String bankUserSign = map.get("bankUserSign") + "";
        SysLuck sysLuck = new SysLuck();
        sysLuck.setBankUserSign(bankUserSign);
        sysLuck.setOrderNo(orderNo);
        sysLuck.setCreateTime(new Date());
        if (null == sysGood || sysGood.getGoodId() == 0) {
            //没中奖
            sysLuck.setStatus("0");
            sysLuck.setReward("0");
            sysLuckMapper.insertSysLuck(sysLuck);
        } else {
            if("1".equals(sysGood.getType())){
                //已中奖且是实物中奖
                sysLuck.setName(sysGood.getCode());
                sysLuck.setStatus("0");
                sysLuck.setReward("1");
                sysLuck.setGoodId(sysGood.getGoodId());
                sysLuck.setMoney(sysGood.getMoney());
                sysLuckMapper.insertSysLuck(sysLuck);
                sysGood.setStock(sysGood.getStock() - 1);
                sysGoodService.updateSysGood(sysGood);
                String key="LD166T";
                long time=System.currentTimeMillis()/1000;
                String proof=jsonObject.getString("proof");
                String lotteryId=jsonObject.getString("id");
                String lotteryName=sysGood.getCode();
                String value=bankUserSign+proof+time+lotteryId+lotteryName+key;
                String token = new String(Md5Util.md5(value).toUpperCase());
                JSONObject data=new JSONObject();
                data.put("bank_user_sign",bankUserSign);
                data.put("proof",proof);
                data.put("time",time);
                data.put("lottery_id",lotteryId);
                data.put("lottery_name",lotteryName);
                data.put("token",token);
                HttpUtil.doPost("https://csp-brdc.dccnet.com.cn/weChatActivity/activity/updatePrizeStatus",data,null);
            }else if("2".equals(sysGood.getType())){
                //虚拟物品中奖
                String openid=map.get("openId")+"";
                String url="https://api.mch.weixin.qq.com/v3/marketing/favor/users/"+openid+"/coupons";
                JSONObject data=new JSONObject();
                data.put("stock_id",sysGood.getCode());//代金券批次id也就是商品编号
                data.put("out_request_no",orderNo);//订单号
                data.put("appid",wxMaService.getWxMaConfig().getAppid());
                data.put("stock_creator_mchid","1605617216");//商户号
                SignUtil signUtil=new SignUtil();
                JSONObject result=HttpUtil.doPost(url,data,signUtil.getToken("POST", HttpUrl.parse(url),data.toJSONString()));
                String expressNo="";
                if(result.containsKey("coupon_id")){
                    expressNo=result.getString("coupon_id");
                }else{
                    throw new BaseException("系统错误,请稍后再试!");
                }
                sysLuck.setName(sysGood.getCode());
                sysLuck.setStatus("1");
                sysLuck.setReward("1");
                sysLuck.setExpress(expressNo);
                sysLuck.setGoodId(sysGood.getGoodId());
                sysLuck.setMoney(sysGood.getMoney());
                sysLuckMapper.insertSysLuck(sysLuck);
                sysGood.setStock(sysGood.getStock() - 1);
                sysGoodService.updateSysGood(sysGood);
            }
        }
    }

    public static int getBulletPrizeIndex(List<SysGood> cubes) {
        int random = -1;
        try {
            //计算总权重
            double sumWeight = 0;
            for (SysGood cube : cubes) {
                sumWeight += cube.getChance();
            }

            //产生随机数
            double randomNumber;
            randomNumber = Math.random();

            //根据随机数在所有奖品分布的区域并确定所抽奖品
            double d1 = 0;
            double d2 = 0;
            for (int i = 0; i < cubes.size(); i++) {
                d2 += Double.parseDouble(String.valueOf(cubes.get(i).getChance())) / sumWeight;
                if (i == 0) {
                    d1 = 0;
                } else {
                    d1 +=
                            Double.parseDouble(String.valueOf(cubes.get(i - 1).getChance())) / sumWeight;
                }
                if (randomNumber >= d1 && randomNumber <= d2) {
                    random = i;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("生成抽奖随机数出错");
        }
        return random;
    }

    /**
     * 新增中奖订单
     *
     * @param sysLuck 中奖订单
     * @return 结果
     */
    @Override
    public int insertSysLuck(SysLuck sysLuck) {
        sysLuck.setCreateTime(DateUtils.getNowDate());
        return sysLuckMapper.insertSysLuck(sysLuck);
    }

    /**
     * 修改中奖订单
     *
     * @param sysLuck 中奖订单
     * @return 结果
     */
    @Override
    public int updateSysLuck(SysLuck sysLuck) {
        sysLuck.setUpdateTime(DateUtils.getNowDate());
        return sysLuckMapper.updateSysLuck(sysLuck);
    }

    /**
     * 批量删除中奖订单
     *
     * @param luckIds 需要删除的中奖订单ID
     * @return 结果
     */
    @Override
    public int deleteSysLuckByIds(Long[] luckIds) {
        return sysLuckMapper.deleteSysLuckByIds(luckIds);
    }

    /**
     * 删除中奖订单信息
     *
     * @param luckId 中奖订单ID
     * @return 结果
     */
    @Override
    public int deleteSysLuckById(Long luckId) {
        return sysLuckMapper.deleteSysLuckById(luckId);
    }

    @Override
    @Transactional
    public String importLuck(List<SysLuck> list) {
        if (StringUtils.isNull(list) || list.size() == 0) {
            throw new BaseException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (SysLuck luck : list) {
            try {
                // 验证是否存在这个用户
                SysLuck u = sysLuckMapper.selectLuckByOrderNo(luck.getOrderNo());
                if (null != u && StringUtils.isNotEmpty(luck.getExpress())) {
                    u.setStatus("1");
                    u.setExpress(luck.getExpress());
                    this.updateSysLuck(u);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、订单号 " + u.getOrderNo() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、订单号 " + u.getOrderNo() + " 不存在或者物流单号为空");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、订单号 " + luck.getOrderNo() + " 更新失败：";
                failureMsg.append(msg + e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，更新失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new CustomException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部更新成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }
}
